package service

import (
	"database/sql"
	"errors"
	"github.com/gogf/gf/container/garray"
	"github.com/gogf/gf/util/gconv"
	"web_api_gogf/app/dao"
	"web_api_gogf/app/model"
)

// SysMenu 系统菜单服务类
var SysMenu = SysMenuService{}

type SysMenuService struct {
}

// GetMenuGroupList 获取分组列表
func (s *SysMenuService) GetMenuGroupList() ([]*model.SysMenuGroups, error) {
	menuGroupList := ([]*model.SysMenuGroups)(nil)
	err := dao.SysMenuGroups.Scan(&menuGroupList)
	if err != nil {
		return nil, err
	}
	return menuGroupList, nil
}

// SaveMenuGroup 保存菜单分组
func (s SysMenuService) SaveMenuGroup(groups *model.SysMenuGroupsReq) (sql.Result, error) {
	result, err := dao.SysMenuGroups.Data(groups).Save()
	if err != nil {
		return nil, err
	}
	return result, nil
}

// GetGroupDataByKey 通过分组key获取分组信息
func (s *SysMenuService) GetGroupDataByKey(groupKey string) (*model.SysMenuGroups, error) {
	menuGroup := new(model.SysMenuGroups)
	err := dao.SysMenuGroups.Where(dao.SysMenuGroups.Columns.GroupKey, groupKey).Scan(&menuGroup)
	if err != nil {
		return nil, err
	}
	return menuGroup, nil
}

// DelMenuGroup 删除菜单分组
func (s SysMenuService) DelMenuGroup(groupIds []uint) (sql.Result, error) {
	r, err := dao.SysMenuGroups.WhereIn(dao.SysMenuGroups.Columns.GroupId, groupIds).Delete()
	if err != nil {
		return nil, err
	}
	return r, err
}

// GetMenuList 通过搜索参数获取菜单列表
func (s *SysMenuService) GetMenuList(searchParams *model.SysMenuGetListReq) ([]*model.SysMenus, error) {
	menuList := ([]*model.SysMenus)(nil)
	modelObj := dao.SysMenus.Safe()
	if searchParams.Name != "" {
		modelObj = modelObj.WhereLike(dao.SysMenus.Columns.Name, "%"+searchParams.Name+"%")
	}
	if searchParams.GroupId != 0 {
		modelObj = modelObj.Where(dao.SysMenus.Columns.GroupId, searchParams.GroupId)
	}
	err := modelObj.Order(dao.SysMenus.Columns.OrderNum + " ASC," + dao.SysMenus.Columns.MenuId + " ASC").Scan(&menuList)
	if err != nil {
		return nil, err
	}
	return menuList, nil
}

// GetMenuListByGroupId 通过分组ID获取菜单列表
func (s *SysMenuService) GetMenuListByGroupId(groupId uint) ([]*model.SysMenusBig, error) {
	menuList := ([]*model.SysMenusBig)(nil)
	err := dao.SysMenus.LeftJoin("sys_permissions", "sys_menus.perm_id=sys_permissions.perm_id").Fields("sys_menus.*,sys_permissions.name as perm_name,sys_permissions.is_public").Where("sys_menus.group_id", groupId).Order("sys_menus.order_num ASC,sys_menus.menu_id ASC").Scan(&menuList)
	if err != nil {
		return nil, err
	}
	return menuList, nil
}

// GetMenuListByKey 通过分组key获取菜单列表
func (s *SysMenuService) GetMenuListByKey(groupKey string) ([]*model.SysMenusBig, error) {
	groupData, err := s.GetGroupDataByKey(groupKey)
	if err != nil {
		return nil, err
	}
	if groupData == nil {
		return nil, errors.New("分组信息不存在")
	}
	menuList, err := s.GetMenuListByGroupId(groupData.GroupId)
	if err != nil {
		return nil, err
	}
	return menuList, nil
}

// GetHasPermMenuList 获取菜单列表
func (s *SysMenuService) GetHasPermMenuList(groupKey string, userPermList *garray.Array) ([]*model.SysMenusBig, error) {
	menuList, err := s.GetMenuListByKey(groupKey)
	if err != nil {
		return nil, err
	}
	menuListArr := garray.New()
	for _, menu := range menuList {
		if menu.PermId == 0 || (menu.PermName != "" && userPermList.Contains(menu.PermName)) {
			menuListArr.Append(menu)
		}
	}
	//组装成树形结构数据
	treeOriginMenuList := ([]model.SysMenusBig)(nil)
	if err := gconv.Structs(menuListArr, &treeOriginMenuList); err != nil {
		return nil, err
	}
	treeMenuList := s.BuildTree(treeOriginMenuList)
	return treeMenuList, nil
}

// BuildTree 构建树结构数据,(由于需要保留菜单结构数据，因此每一次树结构菜单都需要在对应的service中实现，使用公共的树方法无法还原原始菜单数据)
func (s *SysMenuService) BuildTree(resources []model.SysMenusBig) []*model.SysMenusBig {
	//定义根树，既id=0的根节点，我用的时候并不存在于数据库
	var rootResource = model.SysMenusBig{}
	//创建一个map，把父级相同的地址归纳起来
	DataMap := make(map[uint][]*model.SysMenusBig, len(resources))
	//寻找对应的父级，添加子节点集合
	for key := range resources {
		pid := resources[key].ParentId
		DataMap[pid] = append(DataMap[pid], &resources[key])
	}
	for key := range resources {
		if resources[key].ParentId == 0 {
			rootResource.Children = append(rootResource.Children, &resources[key])
		}
		resources[key].Children = DataMap[resources[key].MenuId]
	}
	// 添加完成，既建立树形关系完成
	return rootResource.Children
}

// SaveMenu 保存菜单数据
func (s *SysMenuService) SaveMenu(menuData *model.SysMenuSaveReq) (sql.Result, error) {
	result, err := dao.SysMenus.Data(menuData).Save()
	if err != nil {
		return nil, err
	}
	return result, nil
}

// DelMenu 菜单删除
func (s *SysMenuService) DelMenu(menuIds []uint) (sql.Result, error) {
	result, err := dao.SysMenus.WhereIn(dao.SysMenus.Columns.MenuId, menuIds).Delete()
	if err != nil {
		return nil, err
	}
	return result, err
}
